/*
 *  PlateauGL.cc
 *  hellogl
 *
 *  Created by David Bullado on 28/10/08.
 *  Copyright 2008 __MyCompanyName__. All rights reserved.
 *
 */

#include <QtOpenGL>
#include <iostream>
#include "PlateauGL.h"
#include "Position.h"
#include "glwidget.h"

PlateauGL::PlateauGL() : dessine(false), dessineCases(false), dessineCasesSelected(false) {
	list = glGenLists(1);
	for (int i(0) ; i < 8 ; i++)
		for (int j(0) ; j < 8 ; j++){
			listPositions.push_back(Position(i,j)) ;	
		}
}


PlateauGL::~PlateauGL() {
	glDeleteLists(list, 1);
	deleteCases() ;
}

/* Dessine le plateau en OpenGL */
void PlateauGL::drawPlateau() {
	//double
    	glBindTexture(GL_TEXTURE_2D, GLWidget::tex[2]);  
			glColor4d(1, 1, 1, 0.09);
    	glBegin(GL_QUADS);
		// Haut plateau	  
		// Plaquage de la texture 
				glTexCoord2d(0,0);  	glVertex3d(0,0,0);
				glTexCoord2d(1,0);  	glVertex3d(8, 0, 0) ;
				glTexCoord2d(1,1);  	glVertex3d(8, 0, -8) ;
				glTexCoord2d(0,1);  	glVertex3d(0, 0, -8) ;
		glEnd();
		
/*			glBindTexture(GL_TEXTURE_2D, GLWidget::tex[3]);  
  		
  		// reste plateau
	  	glBegin(GL_QUADS);		
		
				// Face droite
				glTexCoord2d(0,0);  	glVertex3d(8,0,-8);
				glTexCoord2d(0.2,0);  	glVertex3d(8,-1,-8);
				glTexCoord2d(0.2,1);  	glVertex3d(8,-1,8);
				glTexCoord2d(0,1);  	glVertex3d(8,0,8);
				
			// Face derriere
				glTexCoord2d(0,0);  	glVertex3d(8,-1,-8);
				glTexCoord2d(1,0);  	glVertex3d(-8,-1,-8);
				glTexCoord2d(1,1);  	glVertex3d(-8,-1,8);
				glTexCoord2d(0,1);  	glVertex3d(8,-1,8);
				
				// Face gauche
				glTexCoord2d(0,0);  	glVertex3d(-8,1,-8);
				glTexCoord2d(0.2,0);  	glVertex3d(-8,0,-8);
				glTexCoord2d(0.2,1);  	glVertex3d(-8,0,8);
				glTexCoord2d(0,1);  	glVertex3d(-8,1,8);
				
				// Face dessus
				glTexCoord2d(0,0);  	glVertex3d(-8,8,0);
				glTexCoord2d(1,0);  	glVertex3d(8,8,0);
				glTexCoord2d(1,0.2);  	glVertex3d(8,8,1);
				glTexCoord2d(0,0.2);  	glVertex3d(-8,8,1);
				
				// Face dessous
				glTexCoord2d(0,0);  	glVertex3d(-8,-8,0);
				glTexCoord2d(0.2,0);  	glVertex3d(-8,-8,1);
				glTexCoord2d(0.2,1);  	glVertex3d(8,-8,1);
				glTexCoord2d(0,1);  	glVertex3d(8,-8,0);


	  glEnd();
	*/ 	
}

/* Dessine le plateau en OpenGL */
void PlateauGL::drawCasesPicking() { // A Optimiser
	drawCases() ;
}

/* Génère l'objet OpenGL "Plateau"(fait appel à drawPlateau), et retourne l'adresse dans plateauGen */
void PlateauGL::makeCases () {
	int inc (0) ;
	double ew = 8.0 ;// A Généraliser !!!!!!!
	double hauteur, epaisseur ;
	hauteur = -1 ;
	epaisseur = -ew / 10.0 ;
	
	double caseSize = ew / 8.5 ;
	double space = ew / 8.0 ;
	double shift = (space - caseSize)/2.0 ;
	for (std::list<Position>::iterator iter = listPositions.begin(); iter != listPositions.end(); iter++)
	{
		Position & p (*iter);
		listCases[inc] = glGenLists(1);
		glNewList(listCases[inc], GL_COMPILE);
		glLoadName((unsigned int)&p) ;
		glColor3d(1, 1, 0) ;
		glBegin(GL_TRIANGLE_STRIP);
		int i(p.getC()), j(p.getL()) ;
		glVertex3d(i*space+shift,			0, -j*space-shift) ;
		glVertex3d(i*space+shift,			0, -j*space-shift-caseSize) ;
		glVertex3d(i*space+shift+caseSize,	0, -j*space-shift) ;
		glVertex3d(i*space+shift+caseSize,	0, -j*space-shift-caseSize) ;
		glEnd();
		
		glEndList();
		inc++ ;
	}
	dessineCases = true ;
}

void PlateauGL::makeCasesSelected (){
	int inc (0) ;
	double largeur, hauteur, epaisseur ;
	largeur = 8 ;// A Généraliser !!!!!!!

	hauteur = -1 ;
	epaisseur = -largeur / 10.0 ;
	
	double caseSize = largeur / 8.0 ;
	double space = largeur / 8.0 ;
	double shift = (space - caseSize)/2.0 ;
	double o = 0.001 ;
	for (std::list<Position>::iterator iter = listPositions.begin(); iter != listPositions.end(); iter++)
	{
		Position & p (*iter);
		listCasesSelected[inc] = glGenLists(1);
		glNewList(listCasesSelected[inc], GL_COMPILE);
		
		glColor4d(0, 0.2, 1, 0.4);
		glBegin(GL_QUADS);
		int i(p.getC()), j(p.getL()) ;
		glVertex3d(i*space+shift,			o, -j*space-shift) ;
		glVertex3d(i*space+shift,			o, -j*space-shift-caseSize) ;
		glVertex3d(i*space+shift+caseSize,	o, -j*space-shift-caseSize) ;
		glVertex3d(i*space+shift+caseSize,	o, -j*space-shift) ;
		glEnd();
		
		glEndList();
		inc++ ;
	}
	dessineCasesSelected = true ;
}

/* Génère l'objet OpenGL "Plateau"(fait appel à drawPlateau), et retourne l'adresse dans plateauGen */
void PlateauGL::make () {	
	list = glGenLists(1);
    glNewList(list, GL_COMPILE);
		drawPlateau() ;
    glEndList();
	dessine = true ;
}

/* Dessine l'objet Plateau avec un appel de void glCallList( GLuint list ) */
void PlateauGL::draw() {
	if (!dessine)
		make() ;
	
    glCallList (list);
}

template <unsigned int I> inline void PlateauGL::drawCase (){
	glCallList(listCases[I]) ;
	drawCase<I+1>() ;
}
template <> inline void PlateauGL::drawCase< 64 >(){
	glCallList(listCases[63]) ;
}

void PlateauGL::drawCases() {
	if (!dessineCases)
		makeCases() ;
	drawCase< 0 >() ;
}

template <unsigned int I> inline void PlateauGL::deleteCase (){
	glDeleteLists(listCases[I], 1);
	deleteCase<I+1>() ;
}
template <> inline void PlateauGL::deleteCase< 64 >(){
	glDeleteLists(listCases[63], 1);
}

inline void PlateauGL::deleteCases() {
	deleteCase<0>() ;
}

void PlateauGL::drawPicking() {
	glLoadName((unsigned int)this) ;
	if (!dessine) // On laisse ça ?
		make() ;
    glCallList (list);
}

void PlateauGL::drawCasesSelected(const std::list<Position> &l){
glEnable(GL_BLEND) ;
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;  
	if (!dessineCasesSelected)
		makeCasesSelected();
	
	for (std::list<Position>::const_iterator iter = l.begin(); iter != l.end(); iter++)
	{
		glCallList(listCasesSelected[iter->getL()*8+iter->getC()]);
	}
glDisable(GL_BLEND) ;
}

